package checker

import (
	"kumachan/interpreter/lang/textual/ast"
	"kumachan/interpreter/lang/common/name"
	"kumachan/interpreter/lang/common/source"
	"kumachan/interpreter/compiler/checker/typsys"
)


func getDefaultValueFuncName(n name.Name, field string) name.FunctionName {
	var tag = name.FunctionNameTagGenerated("default", field)
	return name.FunctionName {
		Name: name.Name {
			ModuleName: n.ModuleName,
			ItemName:   (n.ItemName + F_Suffix_Default),
		},
		Tag:  tag,
	}
}

func collectTypesDefaultValues(types *typeList, reg FunctionRegistry) source.Errors {
	var errs source.Errors
	for _, item := range *types {
		var def = item.TypeDef
		var node = item.AstNode
		var content_node, ok = node.TypeDef.(ast.VariousTypeDef)
		if !(ok) { continue }
		var box_node, is_box = content_node.TypeDef.(ast.BoxedType)
		if !(is_box) { continue }
		var defaults = box_node.Defaults
		var box = def.Content.(*typsys.Box)
		var inner_record, inner_is_record = getRecord(box.InnerType)
		if !(inner_is_record) {
			if len(defaults) > 0 {
				var loc = content_node.Location
				var err = source.MakeError(loc,
					E_DefaultValuesForNonRecordType {})
				source.ErrorsJoin(&errs, err)
			}
			continue
		}
		var exported = (box.BoxKind == typsys.Isomorphic)
		collectDefaultValue (
			reg,
			&(box.InnerType),
			inner_record,
			defaults,
			def.Parameters,
			def.Name.Name,
			exported,
		)
	}
	return errs
}

func collectFuncInputDefaultValues (
	reg       FunctionRegistry,
	in        *typsys.Type,
	defaults  [] ast.Default,
	loc       source.Location,
	params    [] typsys.Parameter,
	base      name.Name,
	exported  bool,
) *source.Error {
	var record, is_record = getRecord(*in)
	if !(is_record) {
		if len(defaults) > 0 {
			return source.MakeError(loc,
				E_DefaultValuesForNonRecordType {})
		} else {
			return nil
		}
	}
	collectDefaultValue(reg, in, record, defaults, params, base, exported)
	return nil
}

func collectDefaultValue (
	reg       FunctionRegistry,
	rewrite   *typsys.Type,
	record    typsys.Record,
	defaults  [] ast.Default,
	params    [] typsys.Parameter,
	base      name.Name,
	exported  bool,
) {
	for _, default_ := range defaults {
		var loc = default_.Location
		var field_name = ast.Id2String(default_.Key)
		var value = default_.Value
		var index = record.FieldIndexMap[field_name]
		var field = &(record.Fields[index])
		var n = getDefaultValueFuncName(base, field_name)
		var sig = FunctionSignature {
			TypeParameters: params,
			InputOutput:    typsys.Lambda {
				Input:  typsys.UnitType {},
				Output: field.Type,
			},
		}
		var this_node = default_.Node
		var body = ast.Lambda {
			Node:   this_node,
			Input:  ast.VariousPattern {
				Node:    this_node,
				Pattern: ast.PatternTuple {
					Node:  this_node,
					Names: [] ast.Identifier {},
				},
			},
			Output: value,
		}
		var kind = ast.FK_Constant
		var f = craftFunction(n, kind, exported, loc, sig, nil, body)
		reg.InjectFunction(f)
		field.Attr.Default = n
	}
	*rewrite = &typsys.NestedType { Content: record }
}


